import proj4 from 'proj4';
import * as proj from 'ol/proj';
import Matrix2 from "./Matrix2";
import Coordtransform from "./Coordtransform";

export default {

    /**
     * CGCS4498平面坐标与CGCS4490经纬度坐标互相转换
     * @param coord
     * @returns {*}
     */
    coordTransform: function (coord) {

        let projection4490 = new proj.Projection({
            code: 'EPSG:4490',
            units: 'degrees',
            axisOrientation: 'neu'
        })

        let projection4498 = new proj.Projection({
            code: 'EPSG:4498',
            units: 'degrees',
            axisOrientation: 'neu'
        })

        proj4.defs("EPSG:4490", "+proj=longlat +ellps=GRS80 +no_defs");
        proj4.defs("EPSG:4498","+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=20500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");

        proj.addProjection(projection4490);
        proj.addProjection(projection4498);

        proj.addCoordinateTransforms("EPSG:4498", "EPSG:4490", coordinate => {

            return proj4("EPSG:4498", "EPSG:4490", coordinate);

        }, coordinate => {

            return proj4("EPSG:4490", "EPSG:4498", coordinate);
        })

        return proj.transform(coord, "EPSG:4498", "EPSG:4490");
    },

    /**
     * 经纬度转墨卡托
     * @param lngLat Array
     * @returns {{x: number, y: number}}
     */
    lngLatToMercator: function (lngLat) {

        lngLat = new Coordtransform().gcj02Towgs84(lngLat[0], lngLat[1]);

        let mercator = {x: 0, y: 0};
        let x = lngLat[0] * 20037508.34 / 180;
        let y = (Math.PI / 180.0) * lngLat[1];
        let t = Math.PI / 4.0 + y / 2.0;
        y = (20037508.3427892 * Math.log(Math.tan(t))) / Math.PI;

        mercator.x = x;
        mercator.y = y;

        return mercator;
    },

    /**
     * 墨卡托转经纬度
     * @param mercator
     * @returns {number[]}
     */
    mercatorToLngLat: function (mercator) {

        mercator.x = pos.x * elements[0] + pos.z * elements[2] + mapCenter.x;
        mercator.y = pos.x * elements[1] + pos.z * elements[3] + mapCenter.y;

        let x = mercator.x / 20037508.34 * 180;
        let y = mercator.y / 20037508.34 * 180;
        y = 180 / Math.PI * (2 * Math.atan(Math.exp(y * Math.PI / 180)) - Math.PI / 2);

        return new Coordtransform().wgs84Togcj02(x, y);
    },

    /**
     * 计算过度矩阵
     * @param center (0, 0) 对应的经纬度
     * @param xLngLat (1000, 0) 对应的经纬度
     * @param zLngLat (0, 1000) 对应的经纬度
     * @returns {Matrix2}
     */
    getTransitionMatrix: function (center, xLngLat, zLngLat) {

        let mercatorCenter = this.lngLatToMercator(center);
        let mercatorX = this.lngLatToMercator(xLngLat);
        let mercatorZ = this.lngLatToMercator(zLngLat);

        let alpha = new Matrix2();
        alpha.set(mercatorX.x - mercatorCenter.x, mercatorX.y - mercatorCenter.y,
            mercatorZ.x - mercatorCenter.x, mercatorZ.y - mercatorCenter.y
        );

        let beta = new Matrix2();
        beta.set(1000, 0,
            0, 1000
        );

        let tran = new Matrix2();
        tran.getInverse(alpha);
        tran.premultiply(beta);

        return tran;
    },

    /**
     * 经纬度转三维坐标
     * @param lngLat
     * @param height
     * @param tran 过度矩阵
     * @param center 三维场景原点对应的经纬度
     * @returns {{x: number, y: number, z: number}}
     */
    lngLatToXYZ: function (lngLat, height = 0, tran, center) {

        let elements  = tran.elements;
        let mercator  = this.lngLatToMercator(lngLat);
        let mapCenter = this.lngLatToMercator(center);

        return {
            x: (mercator.x - mapCenter.x) * elements[0] + (mercator.y - mapCenter.y) * elements[2],
            y: height,
            z: (mercator.x - mapCenter.x) * elements[1] + (mercator.y - mapCenter.y) * elements[3]
        }
    },

    /**
     * 三维坐标转经纬度
     * @param position
     * @param tranMatrix 过度矩阵
     * @param center 三维场景原点对应的经纬度
     * @returns {[number, number]}
     * @constructor
     */
    XYZToLngLat: function (pos, tranMatrix, center) {

        let tran = new Matrix2();
        tran.getInverse(tranMatrix);

        let elements  = tran.elements;
        let mapCenter = this.lngLatToMercator(center);

        let mercator = {};
        mercator.x = pos.x * elements[0] + pos.z * elements[2] + mapCenter.x;
        mercator.y = pos.x * elements[1] + pos.z * elements[3] + mapCenter.y;

        let x = mercator.x / 20037508.34 * 180;
        let y = mercator.y / 20037508.34 * 180;
        y = 180 / Math.PI * (2 * Math.atan(Math.exp(y * Math.PI / 180)) - Math.PI / 2);

        return new Coordtransform().wgs84Togcj02(x, y);
    }
}